// Plik naglowkowy definiujacy operacje na monitorze/blokadzie typu Czytelnicy-Pisarze
// Jedyna zmiana w stosunku do zwyklego monitora jest to, ze jezeli writer odda sekcje krytyczna
// poprzez sygnal, to po oddaniu jej przez obudzonego to wlasie ten writer ma ja dostac.
// Ponadto (na razie) nic - w szegolnosci niekatualne jest zalozenie z poczatku projektu
// o mozliwosci obudzenia kilku procesow na raz.
//
// _linda_rw_lock - typ reprezentujacy cos (strukture?) co pozwala na realizacje synchronizacji
// _linda_rw_condition - jw. ale dotyczy kolejki/zmiennej warunkowej w monitorze
//
// rp
#ifndef _RWLOCK_H
#define _RWLOCK_H
#include "semaphore.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define _N_PARAM 5

#define _LOCK_NONE 0
#define _LOCK_WRITER 1
#define _LOCK_READER 2

#define writer_count shared_vars[0]
#define reader_count shared_vars[1]
#define waiting_writer_count shared_vars[2]
#define waiting_reader_count shared_vars[3]
#define switched_section shared_vars[4]

typedef struct {
  int master_mutex;
  int writer_mutex;
  int reader_mutex;
  int reader_queue_mutex;
  int switch_mutex;
  
  int *shared_vars;
  
  int our_lock; // to NIE jest zmienna wspoldzielona !
  
  int fd;
  char* path;
} _linda_rw_lock;

typedef struct {
  _linda_rw_lock *lock;
  int wait_semaphore;
} _linda_rw_condition;

// Inicjalizatory i destruktory
// Uwaga: sciezka wskazywana przez path NIE POWINNA istniec
int _linda_create_rw_lock(char* path, _linda_rw_lock* lock);
// Uwaga: sciezka pokazywana przez path MUSI istniec (odwrotnie jak wyzej!)
int _linda_create_rw_condition(_linda_rw_lock* lock, char* path,_linda_rw_condition* cond);

void _linda_destroy_rw_lock(_linda_rw_lock* lock);
void _linda_destroy_rw_condition(_linda_rw_condition* cond);

// Branie istniejacej i odkladanie
int _linda_get_rw_lock(char* path, _linda_rw_lock* lock);
void _linda_leave_rw_lock(_linda_rw_lock* lock);

int _linda_get_rw_condition(_linda_rw_lock* lock, char* path,_linda_rw_condition* cond);

// Zajmowanie i zdejmowanie blokady
void _linda_lock_reader(_linda_rw_lock* lock);
void _linda_release_reader(_linda_rw_lock* lock);

void _linda_lock_writer(_linda_rw_lock* lock);
void _linda_release_writer(_linda_rw_lock* lock);

// Kolejki sygnalow
// UWAGA: obie funkcje powinny byc wywolywane TYLKO i WYLACZNIE majac blokade PISARZA!
void _linda_writer_wait_condition(_linda_rw_condition* cond, int timeout);
void _linda_writer_signal_condition(_linda_rw_condition* cond);
#endif